/********************************************************************************************
 *
 ********************************************************************************************/
#include <includes.h>
#include <LPC17xx.h>
#include <core_cm3.h>
#include <system_LPC17xx.h>
#include <lpc17xx_pinsel.h>
#include <lpc17xx_can.h>


CAN_MSG_Type CAN1_TXMsg, CAN1_RXMsg; //Used as buffer for CAN1
CAN_MSG_Type CAN2_TXMsg, CAN2_RXMsg; //Used as buffer for CAN2


uint8_t CAN_AFSetup(void);
void CAN_IRQHandler(void);
void CAN_InitMessage(void);

//Set amount of AF Section ,the type is WORD (4bytes);
#define CAN1_FC_AMOUNT       (1u) //Amount of FullCAN (Standard Frame Format) Identifier Section  
#define CAN1_SFF_AMOUNT      (4u) //Amount of Standard Frame Format Identifier Section            
#define CAN1_SFFGPR_AMOUNT   (1u) //Amount of Group of Standard Frame Format Identifier Section     
#define CAN1_EFF_AMOUNT      (1u) //Amount of Extended Frame Format Identifier Section             
#define CAN1_EFFGPR_AMOUNT   (2u) //Amount of Group of Extended Frame Format Identifier Section  

#define CAN2_FC_AMOUNT       (1u) //Amount of FullCAN (Standard Frame Format) Identifier Section  
#define CAN2_SFF_AMOUNT      (4u) //Amount of Standard Frame Format Identifier Section            
#define CAN2_SFFGPR_AMOUNT   (1u) //Amount of Group of Standard Frame Format Identifier Section     
#define CAN2_EFF_AMOUNT      (1u) //Amount of Extended Frame Format Identifier Section             
#define CAN2_EFFGPR_AMOUNT   (2u) //Amount of Group of Extended Frame Format Identifier Section 

#define SFF_SA_VALUE         ((CAN1_FC_AMOUNT      + CAN2_FC_AMOUNT)     * 4) 
#define SFF_GPR_SA_VALUE     (((CAN1_SFF_AMOUNT    + CAN2_SFF_AMOUNT)    * 4) + SFF_SA_VALUE) 
#define EFF_SA_VALUE         (((CAN1_SFFGPR_AMOUNT + CAN2_SFFGPR_AMOUNT) * 4) + SFF_GPR_SA_VALUE) 
#define EFF_GPR_SA_VALUE     (((CAN1_EFF_AMOUNT    + CAN2_EFF_AMOUNT)    * 4) + EFF_SA_VALUE) 
#define ENDOFTABLE_VALUE     (((CAN1_EFFGPR_AMOUNT + CAN2_EFFGPR_AMOUNT) * 4) + EFF_GPR_SA_VALUE) 

#if ENDOFTABLE_VALUE > 2048
#error "Can AF limit out"
#endif

#define AF_ADDRESS_MASK        (0x01FFul << 2)  //512*32 (2 kB) RAM

#define SFF_ENABLE             (0u << 12)
#define SFF_DISABLE            (1u << 12)

#define SFF_CONTROLLER_CAN1    (1u << 13)
#define SFF_CONTROLLER_CAN2    (2u << 13)

#define EFF_CONTROLLER_CAN1    (1u << 29)
#define EFF_CONTROLLER_CAN2    (2u << 29)

#if CAN1_FC_AMOUNT > 0
//Full Can ID  For CAN1-------------------------------------------//
const uint16_t Can1_FullCanID[CAN1_FC_AMOUNT * 2] = 
{
	0x0520,0x0522
};
#endif

#if CAN1_SFF_AMOUNT > 0
//Standard Frame Format ID For CAN1-------------------------------//
const uint16_t Can1_SffID[CAN1_SFF_AMOUNT * 2] = 
{
	0x0320,0x0322,0x0324,0x0326,
	0x0328,0x032A,0x032C,0x032E
};
#endif

#if CAN1_SFFGPR_AMOUNT > 0
//Group of Standard Frame Format ID For CAN1----------------------//
const uint16_t Can1_SgprID[CAN1_SFFGPR_AMOUNT * 2] = 
{
	0x0360,0x0370
};
#endif

#if CAN1_EFF_AMOUNT > 0
//Extended Frame Format ID For CAN1-------------------------------//
const uint32_t Can1_EffID[CAN1_EFF_AMOUNT] =
{
    0x05A5A5A0
};
#endif

#if CAN1_EFFGPR_AMOUNT > 0
//Group of Extended Frame Format ID For CAN1----------------------//
const uint32_t Can1_EgprID[CAN1_EFFGPR_AMOUNT] =
{
    0x05A5A5A6,0x05A5A5AD
};
#endif

#if CAN2_FC_AMOUNT > 0
//Full Can ID  For CAN2-------------------------------------------//
const uint16_t Can2_FullCanID[CAN2_FC_AMOUNT * 2] = 
{
	0x0720,0x0722
};
#endif

#if CAN2_SFF_AMOUNT > 0
//Standard Frame Format ID For CAN2-------------------------------//
const uint16_t Can2_SffID[CAN2_SFF_AMOUNT * 2] = 
{
	0x0320,0x0422,0x0424,0x0426,
	0x0428,0x042A,0x042C,0x042E
};
#endif

#if CAN2_SFFGPR_AMOUNT > 0
//Group of Standard Frame Format ID For CAN2----------------------//
const uint16_t Can2_SgprID[CAN2_SFFGPR_AMOUNT * 2] = 
{
	0x0420,0x0422
};
#endif

#if CAN2_EFF_AMOUNT > 0
//Extended Frame Format ID For CAN2-------------------------------//
const uint32_t Can2_EffID[CAN2_EFF_AMOUNT] =
{
    0x06A5A5A0
};
#endif

#if CAN1_EFFGPR_AMOUNT > 0
//Group of Extended Frame Format ID For CAN2----------------------//
const uint32_t Can2_EgprID[CAN2_EFFGPR_AMOUNT] =
{
    0x06A5A5A7,0x06A5A5AF
};
#endif

/************************************************************************
 *                           CAN AF Config
 *********************************************************************** */
uint8_t CAN_AFSetup()
{
	uint16_t Cnt;
	uint16_t RAMIndex;
	
	LPC_CANAF->AFMR = 0x00000001;  //OFF Mode
	
	if(ENDOFTABLE_VALUE > 0x800)   //Limit check
		while(1);
	
	LPC_CANAF->SFF_sa     = SFF_SA_VALUE;
	LPC_CANAF->SFF_GRP_sa = SFF_GPR_SA_VALUE;
	LPC_CANAF->EFF_sa     = EFF_SA_VALUE;
	LPC_CANAF->EFF_GRP_sa = EFF_GPR_SA_VALUE;
	LPC_CANAF->ENDofTable = ENDOFTABLE_VALUE;
	
	RAMIndex = 0;
#if CAN1_FC_AMOUNT > 0
	Cnt = 0;
  while((Cnt) < CAN1_FC_AMOUNT)     //Full Can ID For CAN1
	{
		LPC_CANAF_RAM->mask[RAMIndex ++] = ((Can1_FullCanID[2*Cnt + 1] | SFF_ENABLE | SFF_CONTROLLER_CAN1) & 0xFFFF)|
		                                   ((Can1_FullCanID[2*Cnt] | SFF_ENABLE | SFF_CONTROLLER_CAN1) << 16);
		Cnt ++;
	}
#endif
	
#if CAN2_FC_AMOUNT > 0
	Cnt = 0;
  while((Cnt) < CAN2_FC_AMOUNT)     //Full Can ID For CAN2
	{
		LPC_CANAF_RAM->mask[RAMIndex ++] = ((Can2_FullCanID[2*Cnt + 1] | SFF_ENABLE | SFF_CONTROLLER_CAN2) & 0xFFFF)|
		                                   ((Can2_FullCanID[2*Cnt] | SFF_ENABLE | SFF_CONTROLLER_CAN2) << 16);
		Cnt ++;
	}
#endif
	
#if CAN1_SFF_AMOUNT > 0
	Cnt = 0;
  while((Cnt) < CAN1_SFF_AMOUNT)     //Stand Can ID For CAN1
	{
		LPC_CANAF_RAM->mask[RAMIndex ++] = ((Can1_SffID[2*Cnt + 1] | SFF_ENABLE | SFF_CONTROLLER_CAN1) & 0xFFFF)|
		                                   ((Can1_SffID[2*Cnt] | SFF_ENABLE | SFF_CONTROLLER_CAN1) << 16);
		Cnt ++;
	}
#endif
	
#if CAN2_SFF_AMOUNT > 0
	Cnt = 0;
  while((Cnt) < CAN2_SFF_AMOUNT)     //Stand Can ID For CAN2
	{
		LPC_CANAF_RAM->mask[RAMIndex ++] = ((Can2_SffID[2*Cnt + 1] | SFF_ENABLE | SFF_CONTROLLER_CAN2) & 0xFFFF)|
		                                   ((Can2_SffID[2*Cnt] | SFF_ENABLE | SFF_CONTROLLER_CAN2) << 16);
		Cnt ++;
	}
#endif
	
#if CAN1_SFFGPR_AMOUNT > 0
	Cnt = 0;
  while((Cnt) < CAN1_SFFGPR_AMOUNT)  //Stand Can ID Group For CAN1
	{
		LPC_CANAF_RAM->mask[RAMIndex ++] = ((Can1_SgprID[2*Cnt + 1] | SFF_ENABLE | SFF_CONTROLLER_CAN1) & 0xFFFF)|
		                                   ((Can1_SgprID[2*Cnt] | SFF_ENABLE | SFF_CONTROLLER_CAN1) << 16);
		Cnt ++;
	}
#endif
	
#if CAN2_SFFGPR_AMOUNT > 0
	Cnt = 0;
  while((Cnt) < CAN2_SFFGPR_AMOUNT)  //Stand Can ID Group For CAN2
	{
		LPC_CANAF_RAM->mask[RAMIndex ++] = ((Can2_SgprID[2*Cnt + 1] | SFF_ENABLE | SFF_CONTROLLER_CAN2) & 0xFFFF)|
		                                   ((Can2_SgprID[2*Cnt] | SFF_ENABLE | SFF_CONTROLLER_CAN2) << 16);
		Cnt ++;
	}
#endif
	
#if CAN1_EFF_AMOUNT > 0
	Cnt = 0;
  while((Cnt) < CAN1_EFF_AMOUNT)     //Extended Can ID For CAN1
	{
		LPC_CANAF_RAM->mask[RAMIndex ++] = Can1_EffID[Cnt] | EFF_CONTROLLER_CAN1;
		Cnt ++;
	}
#endif
	
#if CAN2_EFF_AMOUNT > 0
	Cnt = 0;
  while((Cnt) < CAN2_EFF_AMOUNT)     //Extended Can ID For CAN2
	{
		LPC_CANAF_RAM->mask[RAMIndex ++] = Can2_EffID[Cnt] | EFF_CONTROLLER_CAN2;
		Cnt ++;
	}
#endif
	
#if CAN1_EFFGPR_AMOUNT > 0
	Cnt = 0;
  while((Cnt) < CAN1_EFFGPR_AMOUNT)     //Extended Can ID For CAN1
	{
		LPC_CANAF_RAM->mask[RAMIndex ++] = Can1_EgprID[Cnt] | EFF_CONTROLLER_CAN1;
		Cnt ++;
	}
#endif

#if CAN2_EFFGPR_AMOUNT > 0
	Cnt = 0;
  while((Cnt) < CAN2_EFFGPR_AMOUNT)     //Extended Can ID For CAN2
	{
		LPC_CANAF_RAM->mask[RAMIndex ++] = Can2_EgprID[Cnt] | EFF_CONTROLLER_CAN2;
		Cnt ++;
	}
#endif
	return RAMIndex;
}
/*----------------- INTERRUPT SERVICE ROUTINES --------------------------*/
/*********************************************************************//**
 * @brief		CAN_IRQ Handler, control receive message operation
 * param[in]	none
 * @return 		none
 **********************************************************************/
void CAN_IRQHandler()
{
	uint8_t IntStatus;
   // uint32_t data;
	/* get interrupt status
	 * Note that: Interrupt register CANICR will be reset after read.
	 * So function "CAN_IntGetStatus" should be call only one time
	 */
 //   IntStatus = LPC_CAN1->ICR;  //Clear ICR
 	IntStatus = LPC_CAN2->GSR;   //Read State Reg
    
	//check receive interrupt
	if((IntStatus) & 0x01)
	{
		CAN_ReceiveMsg(LPC_CAN2,&CAN2_RXMsg);
	}
	
    
    
    IntStatus = LPC_CAN1->GSR;
	//check receive interrupt
	if((IntStatus>>0)&0x01)
	{
		CAN_ReceiveMsg(LPC_CAN1,&CAN1_RXMsg);
	}
    
    
}

/*-------------------------PRIVATE FUNCTIONS----------------------------*/
/*********************************************************************//**
 * @brief		Initialize transmit and receive message for Bypass operation
 * @param[in]	none
 * @return 		none
 **********************************************************************/
void CAN_InitMessage(void) 
{
  CAN1_TXMsg.format = STD_ID_FORMAT;
	CAN1_TXMsg.id = 0x00001234;
	CAN1_TXMsg.len = 8;
	CAN1_TXMsg.type = DATA_FRAME;
	CAN1_TXMsg.dataA[0] = CAN1_TXMsg.dataA[1] = CAN1_TXMsg.dataA[2] = CAN1_TXMsg.dataA[3] = 0x00;
	CAN1_TXMsg.dataB[0] = CAN1_TXMsg.dataB[1] = CAN1_TXMsg.dataB[2] = CAN1_TXMsg.dataB[3] = 0x00;

	CAN1_RXMsg.format = 0x00;
	CAN1_RXMsg.id = 0x00;
	CAN1_RXMsg.len = 0x00;
	CAN1_RXMsg.type = 0x00;
	CAN1_RXMsg.dataA[0] = CAN1_RXMsg.dataA[1] = CAN1_RXMsg.dataA[2] = CAN1_RXMsg.dataA[3] = 0x00;
	CAN1_RXMsg.dataB[0] = CAN1_RXMsg.dataB[1] = CAN1_RXMsg.dataB[2] = CAN1_RXMsg.dataB[3] = 0x00;
	
	CAN2_TXMsg.format = STD_ID_FORMAT;
	CAN2_TXMsg.id = 0x00001234;
	CAN2_TXMsg.len = 8;
	CAN2_TXMsg.type = DATA_FRAME;
	CAN2_TXMsg.dataA[0] = CAN2_TXMsg.dataA[1] = CAN2_TXMsg.dataA[2] = CAN2_TXMsg.dataA[3] = 0x00;
	CAN2_TXMsg.dataB[0] = CAN2_TXMsg.dataB[1] = CAN2_TXMsg.dataB[2] = CAN2_TXMsg.dataB[3] = 0x00;

	CAN2_RXMsg.format = 0x00;
	CAN2_RXMsg.id = 0x00;
	CAN2_RXMsg.len = 0x00;
	CAN2_RXMsg.type = 0x00;
	CAN2_RXMsg.dataA[0] = CAN2_RXMsg.dataA[1] = CAN2_RXMsg.dataA[2] = CAN2_RXMsg.dataA[3] = 0x00;
	CAN2_RXMsg.dataB[0] = CAN2_RXMsg.dataB[1] = CAN2_RXMsg.dataB[2] = CAN2_RXMsg.dataB[3] = 0x00;
}

/*****************************************************************************************************
 *                        CAN Start
 *****************************************************************************************************/
uint32_t CAN_ModuleConfig()
{
	uint32_t RegData;
	//Initialize CAN1 & CAN2  // set pclk inner
	CAN_Init(LPC_CAN1, 125000);  
	CAN_Init(LPC_CAN2, 125000);
    
    //Enable Interrupt
	CAN_IRQCmd(LPC_CAN1, CANINT_RIE, ENABLE);
    CAN_IRQCmd(LPC_CAN1, CANINT_TIE1, ENABLE);
    CAN_IRQCmd(LPC_CAN1, CANINT_TIE2, ENABLE);
	CAN_IRQCmd(LPC_CAN1, CANINT_TIE3, ENABLE);	
//	LPC_CAN1->IER = CAN_IER_RIE | CAN_IER_TIE1 | CAN_IER_TIE2 | CAN_IER_TIE3;
	
	CAN_IRQCmd(LPC_CAN2, CANINT_RIE, ENABLE);
	CAN_IRQCmd(LPC_CAN2, CANINT_TIE1, ENABLE);
	CAN_IRQCmd(LPC_CAN2, CANINT_TIE2, ENABLE);
	CAN_IRQCmd(LPC_CAN2, CANINT_TIE3, ENABLE);	
//	LPC_CAN2->IER = CAN_IER_RIE | CAN_IER_TIE1 | CAN_IER_TIE2 | CAN_IER_TIE3;
	
	RegData       = LPC_CAN1->ICR;           //Read interrupt state
	RegData       = LPC_CAN2->ICR;           //Read interrupt state
	
	RegData       = LPC_CAN1->GSR;           //read can1 state
	RegData       = LPC_CAN2->GSR;           //read can2 state
	
	RegData       = LPC_CAN1->SR;           //read can1 state
	RegData       = LPC_CAN2->SR;           //read can2 state
	
	LPC_CANAF->AFMR = CAN_AFMR_AccOff;       // Off AF 
	CAN_AFSetup();
//	LPC_CANAF->AFMR = CAN_AFMR_eFCAN;        // AF enable
	LPC_CANAF->AFMR = CAN_AFMR_AccBP;        // AF disable
	
	CAN_InitMessage();
    
	NVIC_ClearPendingIRQ(CAN_IRQn);          //Clear Pending
	NVIC_SetPriority(CAN_IRQn, 0x80);
    NVIC_EnableIRQ(CAN_IRQn);
    

    
//	LPC_CAN1->MOD = 0;                       //All in normal mode                
//	LPC_CAN2->MOD = 0;                       //All in normal mode  

	LPC_CAN1->MOD = 0x01;
	LPC_CAN1->MOD = 0x05;
	LPC_CAN1->MOD = 0x04;
	return RegData;
}


void CAN_PinConfig()
{
    PINSEL_CFG_Type Pin;
    PINSEL_CFG_Type *PinCfg;

    PinCfg = &Pin;
    
    PinCfg->Portnum   = PINSEL_PORT_0 ;                 //CAN1 RX
    PinCfg->Pinnum    = PINSEL_PIN_0 ;
    PinCfg->Funcnum   = PINSEL_FUNC_1 ;
    PinCfg->Pinmode   = PINSEL_PINMODE_TRISTATE  ;
    PinCfg->OpenDrain = PINSEL_PINMODE_NORMAL ;
    PINSEL_ConfigPin(PinCfg); 
    
    PinCfg->Portnum   = PINSEL_PORT_0 ;                 //CAN1 TX
    PinCfg->Pinnum    = PINSEL_PIN_1 ;
    PinCfg->Funcnum   = PINSEL_FUNC_1 ;
    PinCfg->Pinmode   = PINSEL_PINMODE_TRISTATE  ;
    PinCfg->OpenDrain = PINSEL_PINMODE_NORMAL ;
    PINSEL_ConfigPin(PinCfg); 

    PinCfg->Portnum   = PINSEL_PORT_0 ;                 //CAN2 RX
    PinCfg->Pinnum    = PINSEL_PIN_4 ;
    PinCfg->Funcnum   = PINSEL_FUNC_2 ;
    PinCfg->Pinmode   = PINSEL_PINMODE_TRISTATE  ;
    PinCfg->OpenDrain = PINSEL_PINMODE_NORMAL ;
    PINSEL_ConfigPin(PinCfg); 
    
    PinCfg->Portnum   = PINSEL_PORT_0 ;                 //CAN2 TX
    PinCfg->Pinnum    = PINSEL_PIN_5 ;
    PinCfg->Funcnum   = PINSEL_FUNC_2 ;
    PinCfg->Pinmode   = PINSEL_PINMODE_TRISTATE  ;
    PinCfg->OpenDrain = PINSEL_PINMODE_NORMAL ;
    PINSEL_ConfigPin(PinCfg); 
}

void CAN_Task(void * p_arg)
{
    OS_ERR err;
//    uint32_t temp32;
//    uint32_t IntStatus;
    CAN_PinConfig();
    CAN_ModuleConfig();
    
   	CAN1_TXMsg.format = STD_ID_FORMAT;
	CAN1_TXMsg.id = 0x0320;
	CAN1_TXMsg.len = 8;
	CAN1_TXMsg.type = DATA_FRAME;
	CAN1_TXMsg.dataA[0] = 0x11  ;
	CAN1_TXMsg.dataA[1] = 0x12  ;
	CAN1_TXMsg.dataA[2] = 0x13  ;
	CAN1_TXMsg.dataA[3] = 0x15  ;
	CAN1_TXMsg.dataB[0] = 0x11  ;
	CAN1_TXMsg.dataB[1] = 0x12  ;
	CAN1_TXMsg.dataB[2] = 0x13  ;
	CAN1_TXMsg.dataB[3] = 0x15  ;    
    
    CAN2_TXMsg.format = STD_ID_FORMAT;
	CAN2_TXMsg.id = 0x0320;
	CAN2_TXMsg.len = 8;
	CAN2_TXMsg.type = DATA_FRAME;
	CAN2_TXMsg.dataA[0] = 0x22  ;
	CAN2_TXMsg.dataA[1] = 0x33  ;
	CAN2_TXMsg.dataA[2] = 0x44  ;
	CAN2_TXMsg.dataA[3] = 0x55  ;
    

	while(1)
	{
		if(LPC_CAN1->SR & (CAN_SR_TBS1 |CAN_SR_TBS2 |CAN_SR_TBS3) )  //Check has free transmitter or not
		{
//		   CAN_SendMsg(LPC_CAN1,&CAN1_TXMsg);
		}
		
        OSTimeDly(100,OS_OPT_TIME_DLY,&err);
        
		CAN2_TXMsg.dataA[0] ++  ;
		CAN2_TXMsg.dataA[1] ++  ;
		CAN2_TXMsg.dataA[2] ++  ;
		CAN2_TXMsg.dataA[3] ++  ;
	}
}
